package utils;

import java.security.InvalidParameterException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Scanner;

import org.apache.hadoop.fs.Path;

public class Utils {
	public static final String clickSeparator = "\t";
	public static final String userSeparator = "\u0001";
	public static final String auctionSeparator = "\u0001";
	public static final String pvAuctionSeparator1 = "\\+";
	public static final String pvAuctionSeparator2 = "\\|";
	public static final String separator = "\t";
	public static final String unknownStr = "Unknown";
	//public static final String DICT_PATH = "/home/wxz/research/click_prediction/project/clickprediction/dt/20100531/analysis-data.zip";
	//public static final String rootDir = "/home/wxz/research/click_prediction/project/clickprediction/dt/";
	public static final String rootDir = "/group/tbsc-dev/xzwang/clickprediction/";
	public static final String DICT_PATH = "hdfs://hdpnn:9000/group/tbsc-dev/xzwang/analysis-data.zip";
	public static final String otherSort = "other";
	
	public static double log(double value) {
		if (value <= 0)
			return Math.log(0.00000001);
		return Math.log(value);
	}
	
	public static void checkArgs(String[] args) {
		if (args.length == 0) {
			System.out.println("Usage: hadoop jar xx.jar <date> [check continue].");
			System.exit(-1);
		}
	}
	
	public static boolean exitSystem(String[] args) {
		if (args.length == 1)
			return false;
		System.out.println("continue?(0/1)");
		Scanner scanner = new Scanner(System.in);
		int c = scanner.nextInt(); 
		if (c == 0)
			return true;
		return false;
	}
	
	public static boolean isValid(String src) {
		return (src != null && !src.equals("") && !src.equals("-") && !src
				.equals("\\N") && !src.equals("null"));
	}

	public static Path getClickLogPath(String date) {
		String clickPathStr = "/group/taobao/taobao/dw/fact/" + date
				+ "/NewSearchLog/";
		return new Path(clickPathStr);
	}

	public static Path getLocalClickLogPath(String date) {
		String clickPathStr = "/home/cyliu/Data/join/input/clicklog";
		return new Path(clickPathStr);
	}

	public static Path getUserPath() {
		String userPathStr = "/group/taobao/taobao/hive/s_bmw_users_extra/pt=20100318000000/";
		return new Path(userPathStr);
	}

	public static Path getAuctionOnlinePath() {
		String auctionPathStr = "/group/taobao/taobao/hive/r_auction_auctions/pt=20100104000000/if_online=1";
		return new Path(auctionPathStr);
	}

	public static Path getAuctionOfflinePath() {
		String auctionPathB90Str = "/group/taobao/taobao/hive/r_auction_auctions/pt=20100104000000/if_online=0";
		return new Path(auctionPathB90Str);
	}

	public static Path getClickUserPath(String date) {
		String clickUserPathStr = "/group/tbsc-dev/xzwang/cyliu/join/" + date
				+ "/clickUser";
		return new Path(clickUserPathStr);
	}

	public static Path getClickUserAuctionPath(String date) {
		String clickUserAuctionPathStr = "/group/tbsc-dev/xzwang/cyliu/join/"
				+ date + "/clickUserAuction";
		return new Path(clickUserAuctionPathStr);
	}

	public static Path getClickUserAuctionUserPath(String date) {
		String clickUserAuctionUserPathStr = "/group/tbsc-dev/xzwang/cyliu/join/"
				+ date + "/clickUserAuctionUser";
		return new Path(clickUserAuctionUserPathStr);
	}

	public static Path getPvClickPath(String date) {
		String pvClickPathStr = "/group/tbsc-dev/xzwang/cyliu/join/" + date
				+ "/pvClick";
		return new Path(pvClickPathStr);
	}

	public static Path getPvLogPath(String date) {
		String clickPathStr = "/group/taobao/taobao/dw/fact/" + date
				+ "/NewSearchLog/";
		return new Path(clickPathStr);
	}

	public static Path getClickUserinfoPath(String date) {
		String clickUserinfoPathStr = "/group/tbsc-dev/xzwang/cyliu/join/"
				+ date + "/clickUserinfo/";
		return new Path(clickUserinfoPathStr);
	}

	public static Path getClickCountForTimePath(String date, String degree) {
		String clickCountForTimePathStr = "/group/tbsc-dev/xzwang/cyliu/count/clickCountForTime/"
				+ degree + "/" + date;
		return new Path(clickCountForTimePathStr);
	}

	public static Path getClickCountForUserPath(String date, String degree,
			String condition) {
		String clickCountForUserPathStr = "/group/tbsc-dev/xzwang/cyliu/count/clickCountForUser/"
				+ condition + "/" + degree + "/" + date;
		return new Path(clickCountForUserPathStr);
	}

	public static Path getLocalClickCountPerDayPath(String date) {
		String clickCountPerDayPathStr = "/home/cyliu/Data/count/clickCountPerDay";
		return new Path(clickCountPerDayPathStr);
	}

	public static String getRecord(final String[] records, final String separator) {
		StringBuffer sb = new StringBuffer();
		for (String record : records) {
			sb.append(record);
			sb.append(separator);
		}
		return sb.toString().substring(0, sb.toString().length() - 1);
	}
	
	public static String getRecord(String[] records, String separator, int start, int count) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < count; ++i) {
			sb.append(records[start + i]);
			sb.append(separator);
		}
		return sb.toString().substring(0, sb.toString().length() - 1);
	}

	public static HashMap<String, String> sortFilterSetUp() {

		HashMap<String, String> sortMap = new HashMap<String, String>();
		// bid,reserve_price,price_asc ps=reserve_price&ss=ends price_asc
		// 按照价格正序
		sortMap.put("bid", "price_asc");
		sortMap.put("reserve_price", "price_asc");
		sortMap.put("price_asc", "price_asc");
		sortMap.put("ps=reserve_price&ss=ends", "price_asc");
		// _bid,_reserve_price,price_desc _ps=reserve_price&ss=ends
		// price_desc 按照价格逆序
		sortMap.put("_bid", "price_desc");
		sortMap.put("_reserve_price", "price_desc");
		sortMap.put("price_desc", "price_desc");
		sortMap.put("_ps=reserve_price&ss=ends", "price_desc");
		// coefp ps=coefp&ss=ends coefp_desc 人气排序正序
		sortMap.put("coefp", "coefp_desc");
		sortMap.put("ps=coefp&ss=ends", "coefp_desc");
		// _coefp _ps=coefp&ss=ends coefp_asc 人气排序逆序
		sortMap.put("_coefp", "coefp_asc");
		sortMap.put("_ps=coefp&ss=ends", "coefp_asc");
		// _isnewest, isnewest _ps=isnewest&ss=ends, ps=isnewest&ss=ends
		// isnewest 最新上架产品优先
		sortMap.put("_isnewest", "isnewest");
		sortMap.put("isnewest", "isnewest");
		sortMap.put("_ps=isnewest&ss=ends", "isnewest");
		sortMap.put("ps=isnewest&ss=ends", "isnewest");
		// ratesum, credit_asc ps=ratesum&ss=ends ratesum_asc
		sortMap.put("ratesum", "ratesum_asc");
		sortMap.put("credit_asc", "ratesum_asc");
		sortMap.put("ps=ratesum&ss=ends", "ratesum_asc");
		// _ratesum，credit_desc _ps=ratesum&ss=ends ratesum_desc
		sortMap.put("_ratesum", "ratesum_desc");
		sortMap.put("credit_desc", "ratesum_desc");
		sortMap.put("_ps=ratesum&ss=ends", "ratesum_desc");
		// sale_asc ps=volume30day&ss=ends sale_asc
		sortMap.put("sale_asc", "sale_asc");
		sortMap.put("ps=volume30day&ss=ends", "sale_asc");
		// sale_desc _ps=volume30day&ss=ends sale_desc
		sortMap.put("sale_desc", "sale_desc");
		sortMap.put("_ps=volume30day&ss=ends", "sale_desc");
		// _ends, _all, _commend _ps=commend&ss=ends,
		// _ps=ends&ss=reserve_price, _ps=assure&_ss=commend all
		sortMap.put("_ends", "all");
		sortMap.put("_all", "all");
		sortMap.put("_commend", "all");
		sortMap.put("_ps=commend&ss=ends", "all");
		sortMap.put("_ps=ends&ss=reserve_price", "all");
		sortMap.put("_ps=assure&_ss=commend", "all");
		// end, all,commend ps=ends&ss=reserve_price,ps=commend&ss=ends,
		// ps=assure&_ss=commend all
		sortMap.put("end", "all");
		sortMap.put("all", "all");
		sortMap.put("commend", "all");
		sortMap.put("ps=ends&ss=reserve_price", "all");
		sortMap.put("ps=commend&ss=ends", "all");
		sortMap.put("ps=assure&_ss=commend", "all");
		return sortMap;
	}

	public static Path getSortedPvClickPath(String date) {
		String pvClickPathStr = "/group/tbsc-dev/xzwang/cyliu/join/" + date
				+ "/sortedPvClick";
		return new Path(pvClickPathStr);
	}

	public static String getAgeGroup(String birthdayStr) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		Date birthday;
		try {
			birthday = df.parse(birthdayStr);
		} catch (ParseException e) {
			return unknownStr;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(birthday);
		int birthYear = c.get(Calendar.YEAR);
		c.setTime(new Date());
		int thisYear = c.get(Calendar.YEAR);
		int age = thisYear - birthYear;
		if (age >= 0 && age <= 17)
			return "0-17";
		else if (age >= 18 && age <= 22)
			return "18-22";
		else if (age >= 23 && age <= 29)
			return "23-29";
//		else if (age >= 28 && age <= 32)
//			return "28-32";
		else if (age >= 30 && age <= 39)
			return "30-39";
//		else if (age >= 38 && age <= 42)
//			return "38-42";
		else if (age >= 40 && age <= 49)
			return "40-49";
		else if (age >= 50)
			return "Above 50";
		else
			return unknownStr;

	}

	public static String provinceTrim(String province) {
		return province.replaceAll("省", "").replaceAll("[\u4e00-\u9fa5]族自治区",
				"").replace("澳門", "澳门").replace("内蒙古自治区", "内蒙古");
	}

	public static String getLevel(String creditStr) {
		int credit = 0;
		try {
			credit = Integer.parseInt(creditStr);
		} catch (NumberFormatException e) {
			return unknownStr;
		}
		// int[][] minmax = new int[23][2];
		int[][] minmax = { { 0, 1 }, { 1, 4 }, { 4, 11 }, { 11, 41 },
				{ 41, 91 }, { 91, 151 }, { 151, 251 }, { 251, 501 },
				{ 501, 1001 }, { 1001, 2001 }, { 2001, 5001 }, { 5001, 10001 },
				{ 10001, 20001 }, { 20001, 50001 }, { 50001, 100001 },
				{ 100001, 200001 }, { 200001, 500001 }, { 500001, 1000001 },
				{ 1000001, 2000001 }, { 2000001, 5000001 },
				{ 5000001, 10000001 }, { 10000001, 50000001 } };
		for (int i = 0; i < minmax.length; i++) {
			if (in(credit, minmax[i][0], minmax[i][1]))
				return String.valueOf(i);
		}
		return unknownStr;

	}

	public static boolean in(int n, int min, int max) {
		return min <= n && n < max;
	}

	public static String getTime(String time, String field) {
		Date date = new Date();
		SimpleDateFormat clickdf = new SimpleDateFormat("yyyyMMddHHmmss");
		try {
			date = clickdf.parse(time);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int res = 0;
		if ("HourOfDay".equals(field))
			res = c.get(Calendar.HOUR_OF_DAY);
		else if ("DayOfWeek".equals(field))
			res = c.get(Calendar.DAY_OF_WEEK);
		else if ("DayOfMonth".equals(field))
			res = c.get(Calendar.DAY_OF_MONTH);
		return String.valueOf(res);
	}

	public static Path getClickCountForProductPath(String date, String degree,
			String condition) {
		String clickCountForProductPathStr = "/group/tbsc-dev/xzwang/cyliu/count/clickCountForProduct/"
				+ condition + "/" + degree + "/" + date;
		return new Path(clickCountForProductPathStr);
	}

	public static Path getClickCountForPosPath(String date, String type,
			String degree, String condition) {
		String clickCountForPosPathStr = "/group/tbsc-dev/xzwang/cyliu/count/clickCountForPos/"
				+ type + "/" + degree + "/" + condition + "/" + date;
		return new Path(clickCountForPosPathStr);
	}

	public static Path getClickCountForCreditPosPath(String date,
			String condition) {
		String clickCountForCreditPosPathStr = "/group/tbsc-dev/xzwang/cyliu/count/clickCountForPos/credit/"
				+ condition + "/" + date;
		return new Path(clickCountForCreditPosPathStr);
	}

	public static String doubleStrToIntStr(String doubleStr) {
		if (!isValid(doubleStr))
			return "0";
		return String.valueOf((int) Double.parseDouble(doubleStr));
	}

	public static Path getClickCountForPricePosPath(String date,
			String condition) {
		String clickCountForCreditPosPathStr = "/group/tbsc-dev/xzwang/cyliu/count/clickCountForPos/price/"
				+ condition + "/" + date;
		return new Path(clickCountForCreditPosPathStr);
	}

	public static Path getClickCountPath(String date, String condition,
			String degree) {
		String ctrClickCountPathStr = "/group/tbsc-dev/xzwang/cyliu/ctr/clickCount/"
				+ condition + "/" + degree;
		return new Path(ctrClickCountPathStr);
	}

	public static String getUserConditionKey(String condition, String birthday,
			String gender, String province) {
		if ("age".equals(condition) && isValid(birthday)) {
			return getAgeGroup(birthday);
		} else if ("gender".equals(condition) && isValid(gender)) {
			return gender;
		} else if ("province".equals(condition) && isValid(province)) {
			return provinceTrim(province);
		} else
			return unknownStr;
	}

	public static String getPriceRange(String price) {
		double p = Double.parseDouble(price);
		return String.valueOf((int) Math.pow(10, (int) Math.log10(p))) + "-"
				+ String.valueOf((int) Math.pow(10, (int) Math.log10(p) + 1));
	}

	public static String getPos(String degree, String pageNum,
			String numPerPage, String posInPage) {
		if ("PageNum".equals(degree)) {
			return pageNum;
		} else if ("PosInPage".equals(degree)) {
			return posInPage;
		} else if ("PosInAll".equals(degree)) {
			try {
				return String.valueOf((Integer.parseInt(pageNum) - 1)
						* Integer.parseInt(numPerPage)
						+ Integer.parseInt(posInPage));
			} catch (Exception e) {
				return "";
			}
		}
		return "";
	}

	public static String getProductConditionKey(String condition,
			String category, String price, String province) {
		if ("category".equals(condition) && Utils.isValid(category)) {
			return category;
		} else if ("price".equals(condition) && Utils.isValid(price)) {
			return Utils.getPriceRange(price);
		} else if ("province".equals(condition) && Utils.isValid(province)) {
			return Utils.provinceTrim(province);
		} else
			return unknownStr;
	}

	public static Path getPvCountPath(String date, String degree) {
		String pvCountPathStr = "/group/tbsc-dev/xzwang/cyliu/count/pvCount/"
				+ date;
		return new Path(pvCountPathStr);
	}

	public static Path getClickCountForIndexPath(String date, String degree,
			String condition) {
		String clickCountForIndexPathStr = "/group/tbsc-dev/xzwang/cyliu/count/clickCountForIndex/"
				+ degree + "/" + condition + "/" + date;
		return new Path(clickCountForIndexPathStr);
	}

	public static Path getClickAuctionPath(String date) {
		String pathStr = "/group/tbsc-dev/xzwang/cyliu/join/" + date
				+ "/clickAuction";
		return new Path(pathStr);
	}

	public static Path getClickAuctionPvPath(String date) {
		String pathStr = "/group/tbsc-dev/xzwang/cyliu/join/" + date
				+ "/clickAuctionPv";
		return new Path(pathStr);
	}

	public static Path getClickAuctionPvUserPath(String date) {
		String pathStr = "/group/tbsc-dev/xzwang/cyliu/join/" + date
				+ "/clickAuctionPvUser";
		return new Path(pathStr);
	}
	
	@SuppressWarnings("deprecation")
	public static Date getDate(String str) throws InvalidParameterException{
		if (str.length() != 14) 
			throw new InvalidParameterException("str: " + str + " is not valid to parse a string");
		Date date = new Date(
				Integer.parseInt(str.substring(0, 4)),
				Integer.parseInt(str.substring(4, 6)),
				Integer.parseInt(str.substring(6, 8)),
				Integer.parseInt(str.substring(8, 10)),
				Integer.parseInt(str.substring(10, 12)),
				Integer.parseInt(str.substring(12)));
		return date;
	}
	
	public static long getTimeSpan(String str1, String str2) {
		return Math.abs(getDate(str1).getTime() - getDate(str2).getTime()) / 1000;
	}
	
	public static int getYearSpan(Date date1, Date date2) {
		long secondSpan = date1.getTime() - date2.getTime();
		long yearSeconds = (long)1000 * (long)3600 * (long)24 * (long)365;
		return (int) (secondSpan / yearSeconds);
	}
	
	public static boolean isLaterThan(String str1, String str2) {
		Date date1 = getDate(str1);
		Date date2 = getDate(str2);
		return date1.getTime() - date2.getTime() > 0;
	}

}
